// 参考G6插件写法
import {clone, deepMix} from '@antv/util/lib';

const ITEM_TYPE = {
    nodes: 'node',
    edges: 'edge',
    combos: 'combo',
    groups: 'group'
}

/**
 *
 * @param obj {
 *     nodes: deleteNodeModels,
 *     // combps: [],
 *     edges: deleteEdgeModels,
 *     // groups: [],
 * }
 */
export const pushStack = (graph, actionType, before, after) => {
    let data = {
        before: before,
        after: after
    }

    // 与栈里的前一个进行比较，如果相同则合并
    const undoStack = graph.getUndoStack();
    if (!undoStack || undoStack.length === 0) {
        graph.pushStack(actionType, data, 'undo');
    } else {
        // 取出来
        const currentData = undoStack.pop();
        if (currentData) {
            const {action} = currentData;
            if (action === actionType) {
                // 合并
                for (let key in data.before) {
                    data.before[key] = data.before[key].concat(currentData.data.before[key]);
                }
                for (let key in data.after) {
                    data.after[key] = data.after[key].concat(currentData.data.after[key]);
                }
            } else {
                // 塞回去
                graph.pushStack(action, currentData.data, 'undo');
            }

            // 添加数据后塞回去
            graph.pushStack(actionType, data, 'undo');
        }
    }

    console.log(graph.getStackData())
}

/**
 * undo 操作
 */
export const undo = (graph) => {
    // console.log(graph.getStackData())
    const undoStack = graph.getUndoStack();
    // console.log(undoStack)
    if (!undoStack || undoStack.length === 0) {
        return;
    }

    const currentData = undoStack.pop();
    console.log('currentData', currentData)
    if (currentData) {
        const {action} = currentData;
        graph.pushStack(action, clone(currentData.data), 'redo');

        let realAction = action.indexOf('_') !== -1 ? action.split('_')[0] : action;

        let data = currentData.data.before;
        if (action === 'add') {
            data = currentData.data.after;
        }

        if (!data) return;

        switch (realAction) {
            case 'visible': {
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        const item = graph.findById(model.id);
                        if (model.visible) {
                            graph.showItem(item, false);
                        } else {
                            graph.hideItem(item, false);
                        }
                    });
                });
                break;
            }
            case 'render':
            case 'update':
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        graph.updateItem(model.id, model, false);
                    });
                });
                break;
            case 'changedata':
                graph.changeData(data, false);
                break;
            case 'delete': {
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        const itemType = model.itemType;
                        delete model.itemType;
                        graph.addItem(itemType, model, false);
                    });
                });
                break;
            }
            case 'add':
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        graph.removeItem(model.id, false);
                    });
                });
                break;
            case 'group':
                // 删除后加的
                let after = currentData.data.after;
                Object.keys(after).forEach(key => {
                    const array = after[key];
                    if (!array) return;
                    array.forEach(model => {
                        graph.removeItem(model.id, false);
                    });
                });
                // 还原已有的
                let before = currentData.data.before;
                Object.keys(before).forEach(key => {
                    const array = before[key];
                    if (!array) return;
                    array.forEach(model => {
                        const itemType = ITEM_TYPE[key];
                        graph.addItem(itemType, model, false);
                    });
                });
                break;
            default:
        }
    }
}

/**
 * redo 操作
 */
export const redo = (graph) => {
    const redoStack = graph.getRedoStack();

    if (!redoStack || redoStack.length === 0) {
        return;
    }

    const currentData = redoStack.pop();
    console.log(currentData)
    if (currentData) {
        const {action} = currentData;
        let data = currentData.data.after;
        graph.pushStack(action, clone(currentData.data));

        let realAction = action.indexOf('_') !== -1 ? action.split('_')[0] : action;

        if (action === 'delete') {
            data = currentData.data.before;
        }

        if (!data) return;

        switch (realAction) {
            case 'visible': {
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        const item = graph.findById(model.id);
                        if (model.visible) {
                            graph.showItem(item, false);
                        } else {
                            graph.hideItem(item, false);
                        }
                    });
                });
                break;
            }
            case 'render':
            case 'update':
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        graph.updateItem(model.id, model, false);
                    });
                });
                break;
            case 'changedata':
                graph.changeData(data, false);
                break;
            case 'delete':
                if (data.edges) {
                    data.edges.forEach(model => {
                        graph.removeItem(model.id, false);
                    });
                }
                if (data.nodes) {
                    data.nodes.forEach(model => {
                        graph.removeItem(model.id, false);
                    });
                }
                if (data.combos) {
                    data.combos.forEach(model => {
                        graph.removeItem(model.id, false);
                    });
                }
                break;
            case 'add': {
                Object.keys(data).forEach(key => {
                    const array = data[key];
                    if (!array) return;
                    array.forEach(model => {
                        const itemType = model.itemType;
                        delete model.itemType;
                        graph.addItem(itemType, model, false);
                    });
                });
                break;
            }
            case 'group':
                // 删除后加的
                let before = currentData.data.before;
                Object.keys(before).forEach(key => {
                    const array = before[key];
                    if (!array) return;
                    array.forEach(model => {
                        graph.removeItem(model.id, false);
                    });
                });
                // 还原已有的
                let after = currentData.data.after;
                Object.keys(after).forEach(key => {
                    const array = after[key];
                    if (!array) return;
                    array.forEach(model => {
                        const itemType = ITEM_TYPE[key];
                        graph.addItem(itemType, model, false);
                    });
                });
                break;
            default:
        }
    }
}